package net.xdclass.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.constant.CacheKey;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.exception.BizException;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.model.LoginUser;
import net.xdclass.request.CartItemRequest;
import net.xdclass.service.CartService;
import net.xdclass.service.ProductService;
import net.xdclass.until.JsonData;
import net.xdclass.vo.CartItemVO;
import net.xdclass.vo.CartVO;
import net.xdclass.vo.ProductVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductService productService;

    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        long productId = cartItemRequest.getProductId();
        int buyNum = cartItemRequest.getBuyNum();
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        Object cacheObj = myCartOps.get(productId);
        String result = "";
        if (cacheObj != null) {
            result = (String) cacheObj;
        }
        if (StringUtils.isNotBlank(result)) {
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findDetailById(productId);
            if (productVO == null) throw new BizException(BizCodeEnum.CART_FAIL);

            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setProductId(productId);
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());
            myCartOps.put(productId, JSON.toJSONString(cartItemVO));
        } else {
            //存在则新增数量
            CartItemVO cartItem = JSON.parseObject(result, CartItemVO.class);
            cartItem.setBuyNum(cartItem.getBuyNum() + buyNum);
            myCartOps.put(productId, JSON.toJSONString(cartItem));
        }


    }

    @Override
    public void clear() {
        String cartKey = getCartKey();
        redisTemplate.delete(cartKey);
    }

    @Override
    public CartVO getMyCart() {
        List<CartItemVO> cartItemVOS = buildCartItem(false);
        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOS);
        return cartVO;
    }

    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        myCartOps.delete(productId);
    }

    @Override
    public void chageItemNum(CartItemRequest cartItemRequest) {
        //TODO 只能设置已有的 库存
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        String obj = (String) myCartOps.get(cartItemRequest.getProductId());
        if (obj == null) throw new BizException(BizCodeEnum.CART_FAIL);
        CartItemVO cartItemVO = JSON.parseObject((String) obj, CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
        myCartOps.put(cartItemRequest.getProductId(), JSON.toJSON(cartItemVO));
    }

    @Override
    public List<CartItemVO> comfirmOrderCartItems(List<Long> productIdList) {
        //获取全部购物车 选项
        List<CartItemVO> cartItemVOS = buildCartItem(true);
        //根据需要的商品id进行过滤 并清空对应购物项
        List<CartItemVO> collect = cartItemVOS.stream().filter(t -> {
            if (productIdList.contains(t.getProductId())) {
                this.deleteItem(t.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return collect;
    }

    private List<CartItemVO> buildCartItem(Boolean latesPrice) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        List<Object> values = myCartOps.values();
        ArrayList<CartItemVO> cartItemVOS = new ArrayList<>();
        ArrayList<Long> productIds = new ArrayList<>();
        for (Object item : values) {
            CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
            cartItemVOS.add(cartItemVO);
            productIds.add(cartItemVO.getProductId());
        }
        //查询最新价格
        if (latesPrice) {
            setProductLatestPrice(cartItemVOS, productIds);
        }
        return cartItemVOS;
    }

    private void setProductLatestPrice(ArrayList<CartItemVO> cartItemVOS, ArrayList<Long> productIds) {
        List<ProductVO> productVOS = productService.findProductsByIdBatch(productIds);
        Map<Long, ProductVO> collect = productVOS.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
        cartItemVOS.stream().forEach(t -> {
            ProductVO productVO = collect.get(t.getProductId());
            t.setProductTitle(productVO.getTitle());
            t.setProductImg(productVO.getCoverImg());
            t.setAmount(productVO.getAmount());
        });
    }

    private BoundHashOperations<String, Object, Object> getMyCartOps() {
        String cartKey = getCartKey();
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
        return boundHashOperations;
    }

    private String getCartKey() {
        LoginUser loginUser = LoginInterceptor.loginUserThreadLocal.get();
        String cartKey = String.format(CacheKey.CART_KEY, loginUser.getId());
        return cartKey;
    }
}
